package net.zoneland.knowledge.controller;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.ImmutableMap;
import net.zoneland.knowledge.constant.Constants;
import net.zoneland.knowledge.controller.bean.SanHuiYiKeVo;
import net.zoneland.knowledge.model.*;
import net.zoneland.knowledge.service.WorkReminderService;
import net.zoneland.knowledge.service.bean.WorkReminderVo;
import net.zoneland.knowledge.service.bean.IssuedMemberVo;
import net.zoneland.knowledge.utils.LoginUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/workReminder")
public class WorkReminderController extends AbstractBaseApplyInfoController  {

    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WorkReminderController.class);

    @Autowired
    private WorkReminderService workReminderService;

    /**
     * 主工单
     */
    private static final String MAIN_WORK = "mainWork";

    /**
     * 主工单
     */
    private static final String EXCEL_NAME = "党支部工作321提醒";

    /**
     * 查询省公司工单列表
     * @param vo 查询条件
     * @return 省公司工单列表
     */
    @PostMapping("/queryProvinceWorkList")
    public ResponseResult queryProvinceWorkList(@RequestBody final WorkReminderVo vo) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderMainWork> taskReminderMainWorks = workReminderService.getProvinceWorkList(vo);
        res.setData(taskReminderMainWorks);
        return res;
    }

    /**
     * 查询省公司子工单列表
     * @param mainWork 主工单信息
     * @return 省公司子工单列表
     */
    @PostMapping("/queryProvinceSubWorkList")
    public ResponseResult queryProvinceSubWorkList(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderSubWork> taskReminderMainWorks = workReminderService.getProvinceSubWorkList(mainWork.getWorkOrderId());
        final Map<String, Object> map = getSubWorkMap(taskReminderMainWorks, mainWork);

        res.setData(map);
        return res;
    }

    /**
     * 新增、修改省公司工单
     * @param mainWork 工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveOrUpdateProvinceMainWork")
    public ResponseResult saveOrUpdateProvinceWork(final HttpServletRequest request, @RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        final String token = request.getHeader(Constants.TOKEN_NAME);
        final LoginUserPojo loginUserPojo = LoginUtils.getCurrentUserByToken(token);
        final TaskReminderMainWork taskReminderMainWork = workReminderService.saveOrUpdateProvinceWork(mainWork, loginUserPojo);
        res.setData(taskReminderMainWork);
        return res;
    }

    /**
     * 新增、修改省公司子工单
     * @param subWork 子工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveOrUpdateProvinceSubWork")
    public ResponseResult saveOrUpdateProvinceSubWork(@RequestBody final TaskReminderSubWork subWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.saveOrUpdateProvinceSubWork(subWork);

        return res;
    }

    /**
     * 删除省公司主工单
     * @param mainWork 主工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/deleteProvinceMainWork")
    public ResponseResult deleteProvinceMainWork(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.deleteProvinceMainWork(mainWork);

        return res;
    }

    /**
     * 删除省公司子工单
     * @param subWork 子工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/deleteProvinceSubWork")
    public ResponseResult deleteProvinceSubWork(@RequestBody final TaskReminderSubWork subWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.deleteProvinceSubWork(subWork);

        return res;
    }

    /**
     * 下发任务
     * @param request 下发工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/issued")
    public ResponseResult issuedWorkOrder(final HttpServletRequest request) {
        final ResponseResult res = new ResponseResult();
        final LoginUserPojo user = checkCurrentUser(request);
        final List<TaskReminderMainWork> mainWorks = JSON.parseArray(request.getParameter("mainWorks"), TaskReminderMainWork.class);
        workReminderService.issuedWork(mainWorks, user, request);

        return res;
    }

    /**
     * 接受工单信息
     * @param mainWork 工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/acceptWork")
    public ResponseResult acceptWork(@RequestBody final TaskReminderMainWork mainWork){
        final ResponseResult res = new ResponseResult();
        workReminderService.acceptWork(mainWork);

        return res;

    }

    /**
     * 修改市公司主工单
     * @param mainWork 工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveOrUpdateCityMainWork")
    public ResponseResult saveOrUpdateCityMainWork(final HttpServletRequest request, @RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        final String token = request.getHeader(Constants.TOKEN_NAME);
        final LoginUserPojo loginUserPojo = LoginUtils.getCurrentUserByToken(token);
        final TaskReminderMainWork taskReminderMainWork = workReminderService.saveOrUpdateCityMainWork(mainWork, loginUserPojo);
        res.setData(taskReminderMainWork);
        return res;
    }

    /**
     * 修改市公司子工单信息
     * @param subWork 子工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveOrUpdateCitySubWork")
    public ResponseResult updateCitySubWork(@RequestBody final TaskReminderSubWork subWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.updateCitySubWork(subWork);
        return res;
    }

    /**
     * 删除市公司主工单
     * @param mainWork 主工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/deleteCityMainWork")
    public ResponseResult deleteCityMainWork(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.deleteCityMainWork(mainWork);
        return res;
    }

    /**
     * 删除市公司子工单信息
     * @param subWork 子工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/deleteCitySubWork")
    public ResponseResult deleteCitySubWork(@RequestBody final TaskReminderSubWork subWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.deleteCitySubWork(subWork);
        return res;
    }

    /**
     * 新增市公司子工单信息
     * @param subWork 子工单信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveCitySubWork")
    public ResponseResult saveCitySubWork(@RequestBody final TaskReminderSubWork subWork) {
        final ResponseResult res = new ResponseResult();
        workReminderService.saveCitySubWork(subWork);
        return res;

    }

    /**
     * 查询市公司工单列表
     * @param vo 查询条件
     * @return 市公司工单列表
     */
    @PostMapping("/queryCityWorkList")
    public ResponseResult queryCityWorkList(@RequestBody final WorkReminderVo vo) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderMainWork> taskReminderMainWorks = workReminderService.getCityWorkList(vo);
        res.setData(taskReminderMainWorks);
        return res;
    }

    /**
     * 查询市公司子工单列表
     * @param mainWork 主工单信息
     * @return 市公司子工单列表
     */
    @PostMapping("/queryCitySubWorkList")
    public ResponseResult queryCitySubWorkList(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderSubWork> taskReminderSubWorks = workReminderService.getCitySubWorkList(mainWork.getWorkOrderId());
        final Map<String, Object> map = getSubWorkMap(taskReminderSubWorks, mainWork);

        res.setData(map);
        return res;
    }

    /**
     * 查询支部工单列表
     * @param vo 查询条件
     * @return 市公司工单列表
     */
    @PostMapping("/queryBranchWorkList")
    public ResponseResult queryBranchWorkList(@RequestBody final WorkReminderVo vo) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderMainWork> taskReminderMainWorks = workReminderService.getBranchWorkList(vo);
        res.setData(taskReminderMainWorks);
        return res;
    }

    /**
     * 查询支部子工单列表
     * @param mainWork 主工单信息
     * @return 支部子工单列表
     */
    @PostMapping("/queryBranchSubWorkList")
    public ResponseResult queryBranchSubWorkList(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();

        final List<TaskReminderSubWork> taskReminderSubWorks = workReminderService.getBranchSubWorkList(mainWork.getWorkOrderId());
        final TaskReminderMainWork cityMainWork = workReminderService.getCityMainWorkByMainWorkId(mainWork.getParentWorkId());
        final Map<String, Object> map = getSubWorkMap(taskReminderSubWorks, cityMainWork);

        res.setData(map);
        return res;
    }

    /**
     * 查询组织树.
     * @return 组织结构信息
     */
    @GetMapping("/getOrgTree")
    public ResponseResult getOrgTree() {
        final ResponseResult res = new ResponseResult();

        final List<PartyOrg> partyOrgs = workReminderService.getOrgTree();
        final Map<String, List<PartyOrg>> map = partyOrgs.stream()
                .filter(partyOrg -> StringUtils.isNoneBlank(partyOrg.getCompanyName(), partyOrg.getOrgShortName()))
                .collect(Collectors.groupingBy(PartyOrg::getCompanyName, LinkedHashMap::new, Collectors.toList()));
        res.setData(map);
        return res;
    }

    /**
     * 获取市公司下发人员名单
     * @return 市公司下发人员名单
     */
    @GetMapping("/getCityPartyUser")
    public ResponseResult getCityPartyUser() {
        final ResponseResult res = new ResponseResult();
        final Map<String, List<PartyUser>> map = workReminderService.getCityPartyUser()
                .stream()
                .filter(partyUser -> StringUtils.isNotBlank(partyUser.getCompanyName()))
                .collect(Collectors.groupingBy(PartyUser::getCompanyName, LinkedHashMap::new,
                        Collectors.toList()));
        res.setData(map);
        return res;
    }

    /**
     * 获取市公司下发人员名单
     * @return 市公司下发人员名单
     */
    @GetMapping("/getGanshiList")
    public ResponseResult getGanshiList(@RequestParam("companyName") final String companyName) {
        final ResponseResult res = new ResponseResult();
        final Map<String, List<PartyUser>> map = workReminderService.getGanshiByCompany(companyName)
                .stream()
                .filter(partyUser -> StringUtils.isNotBlank(partyUser.getOrgShortName()))
                .collect(Collectors.groupingBy(PartyUser::getOrgShortName, LinkedHashMap::new,
                        Collectors.toList()));
        res.setData(map);
        return res;
    }

    /**
     * 保存默认下发人员信息
     * @param issuedMemberVo 下发人员信息
     * @return 成功、失败状态信息
     */
    @PostMapping("/saveDefaultMembers")
    public ResponseResult saveDefaultMembers(@RequestBody final IssuedMemberVo issuedMemberVo) {
        final ResponseResult res = new ResponseResult();
        workReminderService.saveDefaultMembers(issuedMemberVo.getUserList(),
                issuedMemberVo.getIssuedType(),
                issuedMemberVo.getCompanyName());
        return res;
    }

    /**
     * 获取默认下发人员列表
     * @param companyName 公司名称
     * @return 人员信息列表
     */
    @GetMapping("/getDefaultMembers")
    public ResponseResult getDefaultMembers(@RequestParam("companyName") final String companyName) {
        final ResponseResult res = new ResponseResult();
        final List<IssuedMember> issuedMembers = workReminderService.getDefaultMembers(companyName);
        res.setData(issuedMembers);
        return res;
    }

    /**
     * 自动匹配查询会议信息
     * @param sanHuiYiKeVo 查询条件
     * @return 会议列表
     */
    @PostMapping("/autoSearchMeetingList")
    public ResponseResult autoSearchMeetingList(@RequestBody final SanHuiYiKeVo sanHuiYiKeVo) {
        final ResponseResult res = new ResponseResult();
        final List<SanHuiYiKe> sanHuiYiKeList = workReminderService.autoSearchMeetingList(sanHuiYiKeVo);
        res.setData(sanHuiYiKeList);
        return res;
    }

    /**
     * 查询会议信息
     * @param sanHuiYiKeVo 查询条件
     * @return 会议列表
     */
    @PostMapping("/searchMeetingList")
    public ResponseResult searchMeetingList(@RequestBody final SanHuiYiKeVo sanHuiYiKeVo) {
        final ResponseResult res = new ResponseResult();
        final List<SanHuiYiKe> sanHuiYiKeList = workReminderService.searchMeetingList(sanHuiYiKeVo);
        res.setData(sanHuiYiKeList);
        return res;
    }

    /**
     * 确认完成
     * @param request 参入参数
     * @return 成功、失败状态信息
     */
    @PostMapping("/finishWork")
    public ResponseResult finishWork(final HttpServletRequest request) {
        try {
            final LoginUserPojo user = getAndCheckCurrentUser(request);

            workReminderService.finishWork(request, user);
            return new ResponseResult();
        }catch (final JsonProcessingException e){
            final ResponseResult res = new ResponseResult();
            LOGGER.error("完成任务异常,json转换错误，异常报错:{}，request参数：{}", e, request);
            res.setResult(ResponseResult.FAILED_RESULT);
            res.setMessage("完成任务异常：" + e.getMessage());
            return res;
        }
    }

    /**
     * 根据主工单查询会议信息和附件信息
     * @param mainWork 主工单
     * @return 会议信息和附件信息
     */
    @PostMapping("/searchMeetingByMainWork")
    public ResponseResult searchMeetingByMainWork(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        final List<SanHuiYiKe> sanHuiYiKes = workReminderService.searchMeetingByMainWork(mainWork);
        final List<BranchAttachment> branchAttachments = workReminderService.getBranchAttachmentByMainWork(mainWork.getWorkOrderId());

        final Map<String, Object> map = ImmutableMap.of(
                "meetings", sanHuiYiKes,
                "branchAttachments", branchAttachments);
        res.setData(map);
        return res;
    }

    /**
     * 下载文件.
     * @param request  http请求
     * @param response 响应
     * @param id 附件id
     */
    @GetMapping("/downloadAttachment")
    public void downloadAttachment(final HttpServletRequest request, final HttpServletResponse response,
                                   @RequestParam("id") final String id) {
        try {
            final BranchAttachment branchAttachment = workReminderService.getBranchAttachmentById(id);
            if (Objects.nonNull(branchAttachment)) {
                // 非常重要
                response.reset();
                final String userAgent = request.getHeader("User-Agent");
                String name = branchAttachment.getFileName();
                // 针对IE或者以IE为内核的浏览器：
                if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                    name = java.net.URLEncoder.encode(name, StandardCharsets.UTF_8.name());
                } else {
                    // 非IE浏览器的处理：
                    name = new String(name.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                }
                response.setContentType("application/x-msdownload");
                response.setHeader("Content-Disposition", "attachment; filename=" + name);
                final OutputStream out = response.getOutputStream();
                final byte[] buffer = branchAttachment.getAttachment();
                out.write(buffer, 0, buffer.length);
                out.close();
            } else {
                response.setContentType("text/plain; charset=utf-8");
                response.getWriter().write("文件下载失败");
            }
        } catch (final IOException e) {
            LOGGER.error("下载异常,id:{}", id, e);
        }
    }

    /**
     * 获取工单完成情况信息列表
     * @param mainWork 市公司主工单信息
     * @return 工单完成情况信息列表
     */
    @PostMapping("/getBranchMainWorkByParentWorkId")
    public ResponseResult getBranchMainWorkByParentWorkId(@RequestBody final TaskReminderMainWork mainWork) {
        final ResponseResult res = new ResponseResult();
        final List<TaskReminderMainWork> mainWorks = workReminderService.getBranchMainWorkByParentWorkId(mainWork);
        res.setData(mainWorks);
        return res;
    }

    /**
     * 获取并校验当前用户.
     * @param request http请求
     * @return 当前用户
     */
    private LoginUserPojo checkCurrentUser(final HttpServletRequest request) {
        final LoginUserPojo user = LoginUtils.getCurrentUserByToken(request.getHeader(Constants.TOKEN_NAME));
        Assert.notNull(user, "用户未登录或登录信息不存在");
        return user;
    }

    /**
     * 上传文件
     * @param request 请求参数
     * @return 成功、失败状态信息
     */
    @PostMapping("/uploadFile")
    public ResponseResult uploadFile(final HttpServletRequest request, @RequestParam("mainWork") final String mainWorkStr) {

        final TaskReminderMainWork mainWork;
        try {
            mainWork = objectMapper.readValue(mainWorkStr, TaskReminderMainWork.class);
            final LoginUserPojo user = getAndCheckCurrentUser(request);
            workReminderService.saveFile(request, mainWork, user);
            return new ResponseResult();
        } catch (final JsonProcessingException e) {
            final ResponseResult res = new ResponseResult();
            LOGGER.error("json方法异常{}，mainWork参数错误{},", e, mainWorkStr);
            res.setResult(ResponseResult.FAILED_RESULT);
            res.setMessage("完成任务异常：" + e.getMessage());
            return res;
        }
    }

    /**
     * 根据附件id删除附件信息
     * @param fileId 附件id
     * @return 成功、失败状态信息
     */
    @GetMapping("/deleteFileByFileId")
    public ResponseResult deleteFile(@RequestParam("fileId") final String fileId) {
        workReminderService.deleteBranchAttachmentById(fileId);
        return new ResponseResult();
    }

    /**
     * 根据支部uuid获取当前支部的总支和支部信息列表
     * @param orgUuid 支部uuid
     * @return 当前支部的总支和支部信息列表
     */
    @GetMapping("/get-branch-by-org-uuid")
    public ResponseResult getBranchByOrgUuid(@RequestParam("orguuid") final String orgUuid) {
        final List<PartyOrg> orgList = workReminderService.getBranchByOrgUuid(orgUuid);
        return new ResponseResult("获取成功", orgList);
    }

    /**
     * 321提醒内容导出
     * @param workReminderVo 查询导出数据的条件
     */
    @PostMapping("/reminders-content-export")
    @ResponseBody
    public void remindersContentExport(@RequestBody final WorkReminderVo workReminderVo, final HttpServletResponse response) throws UnsupportedEncodingException {
        setExcelRespProp(response, EXCEL_NAME);
        workReminderService.remindersContentExport(workReminderVo, response);

    }

    /**
     * 合并任务子列表和模板信息
     * @param taskReminderSubWorks 任务子列表
     * @param mainWork 任务主工单查询信息
     * @return 任务子列表和模板信息
     */
    private Map<String, Object> getSubWorkMap(final List<TaskReminderSubWork> taskReminderSubWorks, final TaskReminderMainWork mainWork) {
        // 当前工单的附件
        final List<BranchAttachment> branchAttachments = workReminderService.getBranchAttachmentByMainWork(mainWork.getWorkOrderId());

        // 父工单的附件
        final List<BranchAttachment> parentAttachments = StringUtils.isNotBlank(mainWork.getParentWorkId())
                ? workReminderService.getBranchAttachmentByMainWork(mainWork.getParentWorkId())
                : Collections.emptyList() ;

        return ImmutableMap.of("taskReminderSubWorks", taskReminderSubWorks, "branchAttachments", ListUtils.union(branchAttachments, parentAttachments));
    }

}
